package com.hzqy.commons.utils;

import java.io.*;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.URLDecoder;
import java.net.UnknownHostException;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.UUID;

import javax.annotation.Resource;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.context.support.WebApplicationContextUtils;

import com.hzqy.service.commons.CommonsServiceBean;

public class SystemKeyUtil{
	private static final Log LOG = LogFactory.getLog(SystemKeyUtil.class);
	private static boolean KEY_SWITCH = false;//true 开启密钥验证 ；false 关闭密钥验证
	private static int LAST_RUN_TIME = -10000;//数据库运行时间
	private static long MAX_CACHE_TIME = 10*1000; //缓存超过10分钟，就去数据库中查询一次
	private static long CACHE_BEGIN_TIME = System.currentTimeMillis(); //缓存开始时间
	private static boolean isTrue = true;

	public static void main(String[] args){

	}

	public static String getSysKey(String privateKey,String startTime,String endTime) {
		if(KEY_SWITCH){
			Map<String,Object> signParams = new HashMap<String,Object>();
			//LOG.debug("privateKey:"+privateKey);
			InetAddress ia = null;
			String mac = "";
			String user_name = "";
			try {
				ia = InetAddress.getLocalHost();
			} catch (UnknownHostException e) {
				//LOG.error("获取本机信息出错",e);
			}
			/*try {
				mac = getLocalMac(ia);

			} catch (SocketException e) {
				//LOG.error("获取本机mac出错",e);
			}*/
			mac="1222";
			//LOG.debug("mac:"+mac);

			String CONFIG_FILE_NAME = "config.properties";
			Properties p = new Properties();
			String path = null;

			path = SystemKeyUtil.class.getResource("/").getPath()
					+ CONFIG_FILE_NAME;
			FileInputStream fis = null;
			try {
				path = URLDecoder.decode(path, "utf-8");
				fis = new FileInputStream(new File(path));
				p.load(fis);
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}finally {
				if (fis != null) {
					try {
						fis.close();
					} catch (IOException e) {
					}
				}
			}

			user_name = p.getProperty("connection.user_name");
			String password = p.getProperty("connection.password");

			signParams.put("mac", mac);
			signParams.put("user_name", user_name);
			signParams.put("password", password);
			signParams.put("startTime", startTime);
			signParams.put("endTime", endTime);
			String jvmVersion = System.getProperty("java.version");
			signParams.put("jvmVersion", jvmVersion);
			String userName = System.getProperty("user.name");
			signParams.put("userName", userName);
			String osName = System.getProperty("os.name");
			signParams.put("osName", osName);

			//LOG.debug("user_name:"+user_name);
			//LOG.debug("password:"+password);
			//LOG.debug("startTime:"+startTime);
			//LOG.debug("endTime:"+endTime);
			//LOG.debug("jvmVersion:"+jvmVersion);
			//LOG.debug("userName:"+userName);
			//LOG.debug("osName:"+osName);

			String sysKey = getSign(signParams,privateKey);
			sysKey = MD5Util.MD5_32bit(sysKey);
			String subSysKey = sysKey.substring(0,4)+"-"+sysKey.substring(sysKey.length()-4)+"-"+sysKey.substring(8,12)+"-"+sysKey.substring(16,20);
			//LOG.debug("最终密钥:"+subSysKey);
			return subSysKey;
		}else{
			return "";
		}

	}

	public static boolean complianceKey(String startTime,String endTime,String generatedsystemKey,String systemKey) {
		//LOG.debug("密钥有效时间:"+startTime+"至"+endTime);
		//LOG.debug("生成密钥为:"+generatedsystemKey+"，本地存储密钥为:"+systemKey);
		if(KEY_SWITCH){
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			try {
				Date nowTime = new Date();
				if(nowTime.after(sdf.parse(startTime))&&nowTime.before(sdf.parse(endTime))){
					if(generatedsystemKey.equals(systemKey)){
						return true;
					}else{
						//LOG.debug("密钥不匹配。");
						return false;
					}
				}else{
					//LOG.debug("时间不在有效期内。");
					return false;
				}

			} catch (ParseException e) {
				//LOG.error("密钥比较出错",e);
			}
			return false;
		}else{
			return true;
		}
	}

	public synchronized static boolean complianceDatabaseRuntime(ServletContext servletContext){
		if(KEY_SWITCH){
			WebApplicationContext webApplicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);
			CommonsServiceBean commonsServiceBean = (CommonsServiceBean)webApplicationContext.getBean("commonsServiceBean");
			Map<String,Object> map = commonsServiceBean.selectDatabaseRuntime();
			int nowRunTime = Integer.parseInt((String) map.get("Value"));
			//LOG.debug("数据库上次存储运行时间："+LAST_RUN_TIME+" 数据库现在运行时间："+nowRunTime);
			if(LAST_RUN_TIME==-10000){
				LAST_RUN_TIME = nowRunTime;
				return true;
			}else{
				if(nowRunTime>=LAST_RUN_TIME){
					LAST_RUN_TIME = nowRunTime;
					return true;
				}else{
					LOG.debug("数据库运行时间比较：false"+"数据库上次存储运行时间："+LAST_RUN_TIME+" 数据库现在运行时间："+nowRunTime);
					LAST_RUN_TIME = nowRunTime;
					return false;
				}
			}
		}else{
			return true;
		}
	}

	public synchronized static boolean complianceKeyAndDBTime(String startTime,String endTime,String generatedsystemKey,String systemKey,ServletContext servletContext){
		if(!isTrue)
			return isTrue;

		long nowTime = System.currentTimeMillis();
		boolean b2 = true;
		//LOG.debug("现在时间："+nowTime+"上次缓存开始时间："+CACHE_BEGIN_TIME);
		
		/*if(nowTime-CACHE_BEGIN_TIME>MAX_CACHE_TIME||LAST_RUN_TIME==-10000) { //判断缓存时间是否已经超过MAX_CACHE_TIME了，超过则更新时间和从数据库中重新查询
			CACHE_BEGIN_TIME = nowTime;
			try {
				b2 = complianceDatabaseRuntime(servletContext);
				//LOG.debug("数据库运行时间缓存过期重新获取为："+LAST_RUN_TIME);
			} catch(Exception e) {
				LOG.error("数据库运行时间缓存过期重新获取异常：",e);
				b2 = false;
			}
		}else{
			//LOG.debug("数据库运行时间缓存中，不做比较");
			b2 = true;
		}*/

		boolean b1 = complianceKey(startTime, endTime, generatedsystemKey, systemKey);

		//该功能暂未上线，b1、b2默认设置为true
		//b1 = true;
		//b2 = true;

		if(b1&&b2){
			isTrue = true;
		}else{
			isTrue = false;
		}
		return isTrue;
	}


	private static String getLocalMac(InetAddress ia) throws SocketException {
		// TODO Auto-generated method stub
		//获取网卡，获取地址
		byte[] mac = NetworkInterface.getByInetAddress(ia).getHardwareAddress();
		StringBuffer sb = new StringBuffer("");
		for(int i=0; i<mac.length; i++) {
			if(i!=0) {
				sb.append("-");
			}
			//字节转换为整数
			int temp = mac[i]&0xff;
			String str = Integer.toHexString(temp);
			if(str.length()==1) {
				sb.append("0"+str);
			}else {
				sb.append(str);
			}
		}
		return sb.toString();
	}

	public static String getSign(Map<String,Object> signParams,String appSecret){
		//2.1 获取signParams中的key值
		StringBuilder sb = new StringBuilder();
		List<String> keyList = new ArrayList<String> (signParams.size());
		for (Map.Entry entry : signParams.entrySet()) {
			keyList.add((String) entry.getKey());
		}
		//2.2将key值进行排序
		Collections.sort(keyList);

		//2.3 按照该方式拼接成字符串 appSecret+key+map.get(key)+appSecret
		sb.append(appSecret);
		for (String key : keyList) {
			sb.append(key).append(signParams.get(key));
		}
		sb.append(appSecret);

		//LOG.debug(sb.toString());
		//2.4 SHA1 加密后 将二进制输出为字符串
		try{
			byte[] sha1Digest = getSHA1Digest(sb.toString());
			return byte2hex(sha1Digest);
		} catch (IOException e) {
			LOG.debug("签名失败");
		}
		return "";
	}

	private static byte[] getSHA1Digest(String data) throws IOException {
		byte[] bytes = null;
		try {
			MessageDigest md = MessageDigest.getInstance("SHA-1");
			bytes = md.digest(data.getBytes("UTF-8"));
		} catch (GeneralSecurityException gse) {
			//throw new IOException(gse.getMessage());
		}
		return bytes;
	}

	private static String byte2hex(byte[] bytes){
		StringBuilder sign = new StringBuilder();
		for (int i = 0; i < bytes.length; i++) {
			String hex = Integer.toHexString(bytes[i] & 0xFF);
			if (hex.length() == 1) {
				sign.append("0");
			}
			sign.append(hex.toUpperCase());
		}
		return sign.toString();
	}

}
